
// 早晚需要把这部分代码再整理下，命名规范些


/**
 * 命名空间
 * 
 */
var ExpLink = ExpLink || {};

/**
 * 地图命名空间中添加对全局window的引用
 */
ExpLink.global = this;

/**
 * 标示是否是调试状态
 */
ExpLink.DEBUG = true;
/**
 * 基础方法。此类中方法用于实现继承、类型判断等等。
 */

/**
 * 基本。此类中方法用于实现继承、类型判断等等。
 */
ExpLink.Utility = function()
{
}
/**
 * 继承
 */
ExpLink.Utility.inherits = function(childCtor, parentCtor)
{
	/** @构造 */
	function tempCtor()
	{
	};
	tempCtor.prototype = parentCtor.prototype;
	childCtor.superClass_ = parentCtor.prototype;
	childCtor.prototype = new tempCtor();
	/** @重新定义构造 */
	childCtor.prototype.constructor = childCtor;
	/** @定义一个可以访问超类中方法的方法 */
	childCtor.base = function(me, methodName, var_args)
	{
		var args = Array.prototype.slice.call(arguments, 2);
		return parentCtor.prototype[methodName].apply(me, args);
	};
};

/**
 * 执行基类构造函数
 */
ExpLink.Utility.base = function(me, opt_methodName, var_args)
{
	var caller = arguments.callee.caller;

	if(ExpLink.DEBUG)
	{
		if(!caller)
		{
			throw Error("无法调用方法执行者");
		}
	}
	if(caller.superClass_)
	{
		// 调用基类构造.
		return caller.superClass_.constructor.apply(me, Array.prototype.slice.call(arguments, 1));
	}

	var args = Array.prototype.slice.call(arguments, 2);
	var foundCaller = false;
	for (var ctor = me.constructor; ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor)
	{
		if(ctor.prototype[opt_methodName] === caller)
		{
			foundCaller = true;
		}
		else if(foundCaller)
		{
			return ctor.prototype[opt_methodName].apply(me, args);
		}
	}
	// 处理无法找到调用者的异常情况。
	if(me[opt_methodName] === caller)
	{
		return me.constructor.prototype[opt_methodName].apply(me, args);
	}
	else
	{
		throw Error("调用失败");
	}
};

/**
 * 判断变量是否定义
 */
ExpLink.Utility.isDef = function(val)
{
	return val != undefined;
}

/**
 * 判断变量是否初始化
 */
ExpLink.Utility.isNull = function(val)
{
	return val === null;
}

/**
 * 判断变量是否定义及初始化
 */
ExpLink.Utility.isDefAndNotNull = function(val)
{
	return val != null;
};

/**
 * 判断变量类型
 */
ExpLink.Utility.typeOf = function(value)
{
	var s = typeof value;
	if(s == 'object')
	{
		if(value)
		{
			if(value instanceof Array)
			{
				return 'array';
			}
			else if(value instanceof Object)
			{
				return s;
			}
			var className = Object.prototype.toString.call((value));
			if(className == '[object Window]')
			{
				return 'object';
			}
			if((className == '[object Array]' || typeof value.length == 'number' && typeof value.splice != 'undefined' && typeof value.propertyIsEnumerable != 'undefined' && !value.propertyIsEnumerable('splice')))
			{
				return 'array';
			}
			if((className == '[object Function]' || typeof value.call != 'undefined' && typeof value.propertyIsEnumerable != 'undefined' && !value.propertyIsEnumerable('call')))
			{
				return 'function';
			}
		}
		else
		{
			return 'null';
		}
	}
	else if(s == 'function' && typeof value.call == 'undefined')
	{
		return 'object';
	}
	return s;
};

/**
 * 判断变量是否为数组类型
 */
ExpLink.Utility.isArray = function(val)
{
	return ExpLink.Utility.typeOf(val) == 'array';
};

/**
 * 字符串
 */
ExpLink.Utility.isString = function(val)
{
	return typeof val == 'string';
};

/**
 * 布尔类型
 */
ExpLink.Utility.isBoolean = function(val)
{
	return typeof val == 'boolean';
};

/**
 * 数字.
 */
ExpLink.Utility.isNumber = function(val)
{
	return typeof val == 'number';
};

/**
 * 方法
 */
ExpLink.Utility.isFunction = function(val)
{
	return ExpLink.Utility.typeOf(val) == 'function';
};

/**
 * 基类对象
 */
ExpLink.Utility.isObject = function(val)
{
	var type = typeof val;
	return type == 'object' && val != null || type == 'function';
};

/**
 * 将字符串转换成对象 通过try/catch实现异常捕获，效率是最低的。 默认JSON可用
 */
ExpLink.Utility.parse = function(val)
{
	try
	{
		var result = JSON.parse(val);
		return {
			status : true,
			result : result
		};
	}
	catch (e)
	{
		return {
			status : false,
			result : null
		};
	}
}

/**
 * 创建一个GUID
 */
ExpLink.Utility.guid = function()
{
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)
	{
		var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
		return v.toString(16);
	});
};

// ///////////////// 事件
/**
 * 事件对象
 */
ExpLink.Event = function(type, target)
{
	this.type = type;
	this.returnValue = true;
	this.target = target || null;
	this.currentTarget = null;
};

// //////////// 观察者对象
/**
 * 事件对象
 */
ExpLink.Observable = function()
{

}
/**
 * 添加事件
 */
ExpLink.Observable.prototype.add = function(type, handler, key)
{
	if(!ExpLink.Utility.isFunction(handler))
	{
		return;
	}
	!this.__listeners && (this.__listeners = {});
	var t = this.__listeners, id;
	if(typeof key == "string" && key)
	{
		if(/[^\w\-]/.test(key))
		{
			throw ("nonstandard key:" + key);
		}
		else
		{
			handler.hashCode = key;
			id = key;
		}
	}
	type.indexOf("on") != 0 && (type = "on" + type);
	typeof t[type] != "object" && (t[type] = {});
	id = id || ExpLink.Utility.guid();
	handler.hashCode = id;
	t[type][id] = handler;

	return id;
};
/**
 * 移除事件
 */
ExpLink.Observable.prototype.remove = function(type, handler)
{
	if(ExpLink.Utility.isFunction(handler))
	{
		handler = handler.hashCode;
	}
	else if(!ExpLink.Utility.isString(handler))
	{
		return;
	}
	!this.__listeners && (this.__listeners = {});
	type.indexOf("on") != 0 && (type = "on" + type);
	var t = this.__listeners;
	if(!t[type])
	{
		return;
	}
	t[type][handler] && delete t[type][handler];
};
/**
 * 分发事件
 */
ExpLink.Observable.prototype.dispatch = function(event, options)
{
	if(ExpLink.Utility.isString(event))
	{
		event = new ExpLink.Event(event);
	}
	!this.__listeners && (this.__listeners = {});
	options = options || {};
	for ( var i in options)
	{
		event[i] = options[i];
	}
	var i, t = this.__listeners, p = event.type;
	event.target = event.target || this;
	event.currentTarget = this;
	p.indexOf("on") != 0 && (p = "on" + p);
	ExpLink.Utility.isFunction(this[p]) && this[p].apply(this, arguments);
	if(typeof t[p] == "object")
	{
		for (i in t[p])
		{
			t[p][i].apply(this, arguments);
		}
	}
	return event.returnValue;
};

/**
 * 计算方法
 */
ExpLink.algo = function()
{
}

/**
 * 返回两个数组的交集和差集 result.inter : 交集 result.diff : 差集 1-2
 */
ExpLink.algo.interdiff = function(firstArr, firstFn, secondArr, secondFn)
{
	if(!ExpLink.Utility.isDefAndNotNull(firstArr) || !ExpLink.Utility.isArray(firstArr))
	{
		return null;
	}
	if(!ExpLink.Utility.isDefAndNotNull(secondArr) || !ExpLink.Utility.isArray(secondArr))
	{
		return firstArr;
	}
	if(!ExpLink.Utility.isDefAndNotNull(firstFn))
	{
		firstFn = function(ele)
		{
			return ele
		};
	}
	if(!ExpLink.Utility.isDefAndNotNull(secondFn))
	{
		secondFn = firstFn;
	}

	var resultInterArr = [];
	var resultDiffArr = [];
	var dic = {};
	for (var i = 0, length = secondArr.length; i < length; i++)
	{
		var item = secondFn.call(secondArr[i], secondArr[i]);
		dic[item] = true;
	}

	for (var i = 0, length = firstArr.length; i < length; i++)
	{
		var item = firstFn.call(firstArr[i], firstArr[i]);
		if(dic[item])
		{
			resultInterArr.push(firstArr[i]);
		}
		else
		{
			resultDiffArr.push(firstArr[i]);
		}
	}

	return {
		inter : resultInterArr,
		diff : resultDiffArr
	};
}

/**
 * 模拟Linq data 只接受数组哦
 */
ExpLink.algo.linq = function(data)
{
	return new ExpLink.algo.linq.Enumberable(data);
};

/**
 * 可枚举对象 暂时未实现 next 等方法
 */
ExpLink.algo.linq.Enumberable = function(data)
{
	this._dataItem = data;
}

/**
 * 返回数组对象 此方法不返回对象本身
 */
ExpLink.algo.linq.Enumberable.prototype.toArray = function()
{
	return this._dataItem;
}

/**
 * 计算数组的差集 此方法返回枚举对象本身
 */
ExpLink.algo.linq.Enumberable.prototype.difference = function(otherArr, firstFn, secondFn)
{
	if(!ExpLink.Utility.isDefAndNotNull(otherArr) || !ExpLink.Utility.isArray(otherArr))
	{
		return this;
	}
	if(!ExpLink.Utility.isDefAndNotNull(firstFn))
	{
		firstFn = function(ele)
		{
			return ele
		};
	}
	if(!ExpLink.Utility.isDefAndNotNull(secondFn))
	{
		secondFn = firstFn;
	}

	var resultArr = [];
	var dic = {};
	for (var i = 0, length = otherArr.length; i < length; i++)
	{
		var item = secondFn.call(otherArr[i], otherArr[i]);
		dic[item] = true;
	}

	for (var i = 0, length = this._dataItem.length; i < length; i++)
	{
		var item = firstFn.call(this._dataItem[i], this._dataItem[i]);
		if(!dic[item])
		{
			resultArr.push(this._dataItem[i]);
		}
	}

	this._dataItem = resultArr;

	return this;
}